package com.kudian.restful.service;

import com.kudian.common.persistence.HibernateDao;
import com.kudian.common.service.BaseService;
import com.kudian.restful.dao.*;
import com.kudian.restful.entity.*;
import com.kudian.restful.vo.comment.BindingCommentVO;
import com.kudian.restful.vo.comment.CommentInfoVO;
import com.kudian.restful.vo.comment.CommentItemRetVO;
import com.kudian.restful.vo.comment.QueryCommentVO;
import org.apache.log4j.Logger;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DecimalFormat;
import java.util.*;

/**
 * Created by Administrator on 2016/4/18.
 */
@Service
@Transactional(readOnly = true)
public class CommentService extends BaseService<Comment, Integer> {
    private static final Logger logger = Logger.getLogger(CommentService.class);

    @Autowired
    private CommentDao commentDao;

    @Autowired
    private GoodsDao goodsDao;

    @Autowired
    private OrderInfoDao orderInfoDao;

    @Autowired
    private OrderGoodsDao orderGoodsDao;

    @Autowired
    private LoginSessionDao loginSessionDao;

    @Autowired
    private UsersDao usersDao;

    @Autowired
    private SellerDao sellerDao;

    @Override
    public HibernateDao<Comment, Integer> getEntityDao() {
        return commentDao;
    }

    /**
     * 根据商品id,店铺id检索评论
     * @param vo
     * @return
     */
    public List<CommentItemRetVO> query(QueryCommentVO vo) {
        List<CommentItemRetVO> ret = new ArrayList<CommentItemRetVO>();;
        Short commentType = vo.getCommentType();
        List<Integer> goodsIds = new ArrayList<Integer>();
        if (commentType == null) {
            // 默认给商品做评价
            commentType = 0;
        }
        List<Comment> children = null;

        if (0 == commentType.intValue()) {
            children = commentDao.findbyorder("addTime", false,
                    Restrictions.eq("commentType", commentType), Restrictions.eq("idValue", vo.getIdValue()),
                    Restrictions.ne("parentId", 0), Restrictions.eq("status", (short) 1));
        } else if (1 == commentType.intValue()) {
            // 商铺整体评论

            List<Goods> gs = this.goodsDao.find(Restrictions.eq("sellerId", vo.getIdValue()));
            for (Goods g : gs) {
                goodsIds.add(g.getGoodsId());
            }
            children = commentDao.findbyorder("addTime", false,
                    Restrictions.eq("commentType", (short) 0), Restrictions.in("idValue", goodsIds),
                    Restrictions.ne("parentId", 0), Restrictions.eq("status", (short) 1));
        }

        Map<Integer, CommentItemRetVO> map = new HashMap<Integer, CommentItemRetVO>();
        for (Comment chil : children) {
            CommentItemRetVO item = new CommentItemRetVO();
            item.setCommentId(chil.getCommentId());
            item.setCommentType(chil.getCommentType());
            item.setIdValue(chil.getIdValue());
            item.setContent(chil.getContent());
            item.setCommentRank(chil.getCommentRank());
            item.setUserId(chil.getUserId());
            item.setUserName(chil.getUserName());
            item.setParentId(chil.getParentId());
            item.setAddTime(chil.getAddTime());
            item.setIsAnonymous(chil.getIsAnonymous());
            if (chil.getIsAnonymous()) {
                item.setUserName("");
            }
            map.put(chil.getCommentId(), item);
        }
        Set entrySet = map.entrySet();
        for (Iterator it = entrySet.iterator(); it.hasNext();) {
            CommentItemRetVO node = (CommentItemRetVO) ((Map.Entry) it.next()).getValue();
            if (node.getParentId() == null || node.getParentId().equals(0)) {
            } else {
                if (map.containsKey(node.getParentId())) {
                    ((CommentItemRetVO) map.get(node.getParentId())).setChildren(node);
                }
            }
        }

        List<Comment> cmts = null;
        if (0 == commentType.intValue()) {
            // 取此商品第一层评价，即客户评价
            cmts =commentDao.findbyorder("addTime", false,
                    Restrictions.eq("commentType", commentType), Restrictions.eq("idValue", vo.getIdValue()),
                    Restrictions.eq("parentId", 0), Restrictions.eq("status", (short) 1));
        } else if (1 == commentType.intValue()) {
            cmts =commentDao.findbyorder("addTime", false,
                    Restrictions.eq("commentType", (short) 0), Restrictions.in("idValue", goodsIds),
                    Restrictions.eq("parentId", 0), Restrictions.eq("status", (short) 1));
        }
        for (Comment cmt : cmts) {
            if (ret == null)
                ret = new ArrayList<CommentItemRetVO>();
            CommentItemRetVO item = new CommentItemRetVO();
            item.setCommentId(cmt.getCommentId());
            item.setCommentType(cmt.getCommentType());
            item.setIdValue(cmt.getIdValue());
            item.setContent(cmt.getContent());
            item.setCommentRank(cmt.getCommentRank());
            item.setUserId(cmt.getUserId());
            item.setUserName(cmt.getUserName());
            item.setParentId(cmt.getParentId());
            item.setAddTime(cmt.getAddTime());
            item.setIsAnonymous(cmt.getIsAnonymous());
            if (cmt.getIsAnonymous()) {
                item.setUserName("");
            }
            Set s1 = map.entrySet();
            for (Iterator it = s1.iterator(); it.hasNext();) {
                CommentItemRetVO node = (CommentItemRetVO) ((Map.Entry) it.next()).getValue();
                if (node.getParentId().equals(item.getCommentId())) {
                    item.setChildren(node);
                    break;
                }
            }

            ret.add(item);
        }

        return ret;
    }

    @Transactional(readOnly = false)
    public void binding(BindingCommentVO vo) {
        LoginSession ent = loginSessionDao.get(vo.getAccess_token());
        if (ent == null) {
            logger.error("binding ent null!");
            return;
        }
        Users u = this.usersDao.get(ent.getUserId());
        if (u == null) {
            logger.error("binding Users null!");
            return;
        }
        OrderGoods og = this.orderGoodsDao.findUnique(Restrictions.eq("recId", vo.getRecId()));
        if (og == null) {
            logger.error("binding OrderGoods null!");
            return;
        }
        Goods g = this.goodsDao.get(og.getGoodsId());
        if (g == null) {
            logger.error("binding Goods null!");
            return;
        }
//        Seller s = this.sellerDao.get(g.getSellerId());
//        if (s == null) {
//            logger.error("binding Seller null!");
//            return;
//        }
        OrderInfo oi = this.orderInfoDao.findUnique(Restrictions.eq("orderId", og.getOrderId()), Restrictions.eq("userId", ent.getUserId()));
        if (oi == null) {
            logger.error("binding OrderInfo null!");
            return;
        }

        og.setCommentId(vo.getCommentId());
        orderGoodsDao.save(og);
    }

    /**
     * 返回某一店铺评论信息
     * @param sellerId
     * @return
     */
    public CommentInfoVO queryBySeller(Integer sellerId) {
        CommentInfoVO ret = new CommentInfoVO();
        ret.setCommentRank((short) 0);
        ret.setCommentCount(0);

        String sql = "SELECT \n" +
                "  COUNT(comment_id) cnt,\n" +
                "  IFNULL(SUM(comment_rank), 0) crank\n" +
                "FROM\n" +
                "  COMMENT \n" +
                "WHERE comment_type = 0 \n" +
                "  AND parent_id = 0 \n" +
                "  AND id_value IN (\n" +
                "\tSELECT goods_id FROM goods\n" +
                "\tWHERE seller_id = " + (sellerId == null ? 0 : sellerId)+ "\n" +
                "  )";
        SQLQuery query = commentDao.createSQLQuery(sql);
        List<Object[]> objs = (List<Object[]>) query.list();
        if (objs != null) {
            Object[] obj = objs.get(0);
            ret.setCommentCount(Integer.parseInt(obj[0] == null ? "" : obj[0].toString()));
            int crank = Integer.parseInt(obj[1] ==null ? "" : obj[1].toString());
            if (ret.getCommentCount() != 0) {
                String str = new DecimalFormat("0").format(crank / (double) ret.getCommentCount());
                ret.setCommentRank(Short.parseShort(str));
            } else {
                ret.setCommentRank((short) 0);
            }
        }
        return ret;
    }

    /**
     * 返回某一产品评论信息
     * @param goodsId
     * @return
     */
    public CommentInfoVO queryByGoods(Integer goodsId) {
        CommentInfoVO ret = new CommentInfoVO();
        ret.setCommentRank((short) 0);
        ret.setCommentCount(0);

        String sql = "SELECT \n" +
                "  COUNT(comment_id) cnt,\n" +
                "  IFNULL(SUM(comment_rank), 0) crank\n" +
                "FROM\n" +
                "  COMMENT \n" +
                "WHERE comment_type = 0 \n" +
                "  AND parent_id = 0 \n" +
                "  AND id_value = " + (goodsId == null ? 0 : goodsId);

        SQLQuery query = commentDao.createSQLQuery(sql);
        List<Object[]> objs = (List<Object[]>) query.list();
        if (objs != null) {
            Object[] obj = objs.get(0);
            ret.setCommentCount(Integer.parseInt(obj[0] == null ? "" : obj[0].toString()));
            int crank = Integer.parseInt(obj[1] ==null ? "" : obj[1].toString());
            if (ret.getCommentCount() != 0) {
                String str = new DecimalFormat("0").format(crank / (double) ret.getCommentCount());
                ret.setCommentRank(Short.parseShort(str));
            } else {
                ret.setCommentRank((short) 0);
            }
        }
        return ret;
    }

    /**
     * 返回多个产品评论信息
     * @param goodsIds
     * @return
     */
    public Map<Integer, CommentInfoVO> queryByGoodses(List<Integer> goodsIds) {
        Map<Integer, CommentInfoVO> ret = new HashMap<Integer, CommentInfoVO>();

        if (goodsIds == null || goodsIds.isEmpty()) {
            return ret;
        }

        StringBuffer sb = new StringBuffer();
        sb.append("(");
        boolean isFirst = true;
        for (Integer goodsId : goodsIds) {
            if (isFirst) {
                sb.append(goodsId);
                isFirst = false;
            } else {
                sb.append("," + goodsId);
            }
        }
        sb.append(")");

        String sql = "SELECT \n" +
                "  id_value,\n" +
                "  COUNT(comment_id) cnt,\n" +
                "  IFNULL(SUM(comment_rank), 0) crank\n" +
                "FROM\n" +
                "  COMMENT \n" +
                "WHERE comment_type = 0 \n" +
                "  AND parent_id = 0 \n" +
                "  AND id_value in " + sb.toString() + " \n" +
                "GROUP BY id_value";

        SQLQuery query = commentDao.createSQLQuery(sql);
        List<Object[]> objs = (List<Object[]>) query.list();
        if (objs == null || objs.isEmpty()) {
            return ret;
        }

        for (Object[] obj : objs) {
            CommentInfoVO item = new CommentInfoVO();

            // Object[] obj = objs.get(0);
            Integer key = Integer.parseInt(obj[0] == null ? "0" : obj[0].toString());
            item.setCommentCount(Integer.parseInt(obj[1] == null ? "" : obj[1].toString()));
            int crank = Integer.parseInt(obj[2] == null ? "" : obj[2].toString());
            if (item.getCommentCount() != 0) {
                String str = new DecimalFormat("0").format(crank / (double) item.getCommentCount());
                item.setCommentRank(Short.parseShort(str));
            } else {
                item.setCommentRank((short) 0);
            }
            ret.put(key, item);
        }
        return ret;
    }
}
